package com.om.base;



import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Field.TermVector;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.Scorer;
import org.apache.lucene.search.Searcher;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.SortField;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.TopFieldCollector;
import org.apache.lucene.search.WildcardQuery;
import org.apache.lucene.search.highlight.QueryScorer;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;

import com.om.base.AbstractBean;
import com.om.base.BeanFactory;
import com.om.base.SqlFilter;
import com.om.common.ConfigReader;
import com.sun.java.swing.plaf.windows.WindowsTreeUI.ExpandedIcon;
import com.sun.org.apache.bcel.internal.generic.RETURN;



public class LuceneUtils {
	public final static String INDEX_FLODER_KEY = "lucene.floder";
	
	public static boolean IndexExist(Class cls){
		
		if(cls == null)
			return false;
		
		LuceneIndex bean = (LuceneIndex)BeanFactory.LoadBean(cls);
		String name = bean.getClass().getSimpleName();
		File indexFloder = null;
		File rootFolder = null;
		String rootPath = ConfigReader.GetProptery(INDEX_FLODER_KEY);
		
		if(rootPath == null || "".equals(rootPath)){
			return false;
		}
		
		rootFolder = new File(rootPath);     
		if(!rootFolder.exists()) {     
			return false;   
        }
		String indexFloderPath = rootFolder+ File.separator+name;
		indexFloder = new File(indexFloderPath);  
		if(!indexFloder.exists()) {     
			return false;   
        }

		return true;
	}
	public static void Clear(Class cls){
		
		LuceneIndex bean = (LuceneIndex)BeanFactory.LoadBean(cls);
		String name = bean.getClass().getSimpleName();
		File indexFloder = null;
		File rootFolder = null;
		String rootPath = ConfigReader.GetProptery(INDEX_FLODER_KEY);
		boolean success = false;
		if(rootPath != null && !"".equals(rootPath)){
			rootFolder = new File(rootPath);     
			if(rootFolder.exists()) {     
				String indexFloderPath = rootFolder+ File.separator+name;
				indexFloder = new File(indexFloderPath);
				/*String[] files = indexFloder.list();
				for(int i=0;i<files.length;i++){
					File file = new File(files[i]);
					file.deleteOnExit();
				}
				success = indexFloder.delete();*/
	        }
			 
		}
		
		
	}
	
	public static synchronized void SaveIndex(LuceneIndex bean){
		LuceneUtils utils = new LuceneUtils(bean.getClass());
		utils.saveIndex(bean);
	}
	
	public static  synchronized void SaveIndex(LuceneIndex bean,String floderName,String fields){
		LuceneUtils utils = new LuceneUtils(bean.getClass(),fields);
		utils.floderName =floderName;
		utils.saveIndex(bean);
	}
	
	
	
	
	public static synchronized void SaveIndex(LuceneIndex bean,String floderName,String fields,Analyzer analyzer){
		LuceneUtils utils = new LuceneUtils(bean.getClass(),fields);
		utils.floderName = floderName;
		utils.setAnalyzer(analyzer);
		utils.saveIndex(bean);
	}
	
	public static synchronized void SaveIndex(LuceneIndex bean,Analyzer analyzer){
		LuceneUtils utils = new LuceneUtils(bean.getClass());
		utils.setAnalyzer(analyzer);
		utils.saveIndex(bean);
	}
	
	public static synchronized void SaveIndex(LuceneIndex bean,String floderName,Analyzer analyzer){
		LuceneUtils utils = new LuceneUtils(bean.getClass());
		utils.floderName = floderName;
		utils.setAnalyzer(analyzer);
		utils.saveIndex(bean);
	}
	
	
	
	
	public static synchronized void SaveIndex(ArrayList<AbstractBean>beanList,String fields){
		if(beanList.size()>0){
			LuceneUtils utils = new LuceneUtils(beanList.get(0).getClass(),fields);
			utils.saveIndex(beanList);
		}
		
	}
	public static synchronized void SaveIndex(ArrayList<AbstractBean>beanList,String floderName,String fields){
		if(beanList.size()>0){
			LuceneUtils utils = new LuceneUtils(beanList.get(0).getClass(),fields);
			utils.floderName = floderName;
			utils.saveIndex(beanList);
		}
		
	}
	
	public static synchronized void SaveIndex(ArrayList<AbstractBean>beanList,String floderName,Analyzer analyzer){
		if(beanList.size()>0){
			LuceneUtils utils = new LuceneUtils(beanList.get(0).getClass());
			utils.analyzer = analyzer;
			utils.floderName = floderName;
			utils.saveIndex(beanList);
		}
	}
	
	public static  synchronized void UpdateIndex(ArrayList<AbstractBean>beanList,Analyzer analyzer){
		if(beanList.size()>0){
			LuceneUtils utils = new LuceneUtils(beanList.get(0).getClass());
			utils.analyzer = analyzer;
			utils.updateIndex(beanList);
		}
	}
	
	
	public static synchronized void SaveIndex(ArrayList<AbstractBean>beanList,Analyzer analyzer){
		if(beanList.size()>0){
			LuceneUtils utils = new LuceneUtils(beanList.get(0).getClass());
			utils.analyzer = analyzer;
			utils.saveIndex(beanList);
		}
	}
	
	
	public static synchronized void SaveIndex(ArrayList<AbstractBean>beanList,String floderName,String fields,Analyzer analyzer){
		if(beanList.size()>0){
			LuceneUtils utils = new LuceneUtils(beanList.get(0).getClass(),fields);
			utils.analyzer = analyzer;
			utils.floderName = floderName;
			utils.saveIndex(beanList);
		}
	}
	
	
	
	
	public static List<DataRow> Search(Class cls,String fields,String key){
		LuceneUtils utils = new LuceneUtils(cls);
		return utils.search(fields, key);
	}
	
	public static List<DataRow> Search(Class cls,String fields,String key,Analyzer analyzer){
		LuceneUtils utils = new LuceneUtils(cls,analyzer);
		return utils.search(fields, key);
	}
	
	
	private Class modelClass = null;
	private LuceneIndex bean = null;
	private String floderName = "";
	private String floderPath = "";
	private String fields = "";
	private int maxBufferedDocs = 500;

	private  File rootFolder = null;
	private  IndexSearcher searcher = null;
	private  Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_35);
	private String order =""; 
	private int startIndex =0;
	private int searchLimit =5;
	public boolean usingLuceneQuery = false;
	
	
	public int getStartIndex() {
		return startIndex;
	}
	public void setStartIndex(int startIndex) {
		this.startIndex = startIndex;
	}
	public int getSearchLimit() {
		return searchLimit;
	}
	public void setSearchLimit(int searchLimit) {
		this.searchLimit = searchLimit;
	}
	public Class getModelClass() {
		return modelClass;
	}

	public void setModelClass(Class modelClass) {
		this.modelClass = modelClass;
	}

	public  Searcher getSearcher() {
		return searcher;
	}

	public  void setSearcher(IndexSearcher searcher) {
		this.searcher = searcher;
	}

	public  Analyzer getAnalyzer() {
		return analyzer;
	}

	public  void setAnalyzer(Analyzer analyzer) {
		this.analyzer = analyzer;
	}

	public LuceneUtils(Class cls){
		this.modelClass = cls;
		this.bean = (LuceneIndex)BeanFactory.LoadBean(cls);
	}
	
	public LuceneUtils(Class cls,String fields){
		this.fields = fields;
		this.modelClass =cls;
		this.bean = (LuceneIndex)BeanFactory.LoadBean(cls);
	}
	
	public LuceneUtils(Class cls,Analyzer analyzer){
		this.analyzer = analyzer;
		this.modelClass =cls;
		this.bean = (LuceneIndex)BeanFactory.LoadBean(cls);
	}
	
	
	
	
	public void saveIndex(LuceneIndex  bean,Analyzer analyzer){
		Directory directory = null;     
	    IndexWriter indexWriter = null;     
		try{
			
			directory = FSDirectory.open(this.getIndexFolder(bean.getClass()));     
            indexWriter = new IndexWriter(directory, analyzer, false, IndexWriter.MaxFieldLength.UNLIMITED);     
            indexWriter.setMaxBufferedDocs(maxBufferedDocs);     
            String[] arr = null;
            if(this.fields!=null && !"".equals("")){
            	arr = fields.split(",");
            }
            else{
            	arr = (String[])bean.keySet().toArray();
            }
            Document doc = null; 
            if(bean.PrimaryKeyField==null || bean.PrimaryKeyField.equals("")){
            	bean.PrimaryKeyField = bean.PrimaryKey;
            }
            for(int i=0;i<arr.length;i++){
            	doc = new Document();    
            	String f = arr[i];
            	Field key =null;
            	String value = bean.getStringValue(f);
	           	if("".equals(value))
	           		 continue;
	           	
           	     if(bean.containsSpecialField(f)){
              		key = new Field(f, value.toLowerCase(), Field.Store.YES,bean.getSpecialIndex(f), TermVector.NO);
             	 }
             	 else{
             		 key = new Field(f, value.toLowerCase(), Field.Store.YES,Field.Index.NOT_ANALYZED, TermVector.NO);
             	 }
                doc.add(key); 
                indexWriter.addDocument(doc);     
            }
	  	}catch(Exception ex){
	  		ex.printStackTrace();
	  	}
	}
	

	
	public void saveIndex(LuceneIndex bean){
		Directory directory = null;     
	    IndexWriter indexWriter = null;     
		try{
			directory = FSDirectory.open(this.getIndexFolder(bean.getClass()));     
			 
            Object[] arr = null;
            if(this.fields!=null && !"".equals(fields)){
            	arr = fields.split(",");
            }
            else{
            	arr =bean.keySet().toArray();
            }
            if(bean.PrimaryKeyField==null || bean.PrimaryKeyField.equals("")){
            	bean.PrimaryKeyField = bean.PrimaryKey;
            }
           
            List<DataRow> rows =this.search(bean.PrimaryKeyField, bean.getKeyValue()+"");
        	Document doc = new Document();   
        	
            for(int i=0;i<arr.length;i++){
           
            	 String f = arr[i]+"";
            	 Field key =null;
            	 String value = bean.getStringValue(f);
            	 if("".equals(value))
            		 continue;
            	 if(bean.containsSpecialField(f)){
               		key = new Field(f, value.toLowerCase(), Field.Store.YES,bean.getSpecialIndex(f), TermVector.YES);
              	 }
              	 else{
              		 key = new Field(f, value.toLowerCase(), Field.Store.YES,Field.Index.NOT_ANALYZED, TermVector.YES);
              	 }
                 doc.add(key); 
                   
            }
           
	
        	if(rows.size()==0){
        		indexWriter = new IndexWriter(directory, analyzer, false, IndexWriter.MaxFieldLength.UNLIMITED);     
                indexWriter.setMaxBufferedDocs(maxBufferedDocs); 
        		indexWriter.addDocument(doc);  
        		 
        	}
        	else{
        		indexWriter = new IndexWriter(directory, analyzer, false, IndexWriter.MaxFieldLength.UNLIMITED);     
                indexWriter.setMaxBufferedDocs(maxBufferedDocs); 
        		indexWriter.updateDocument(new Term(bean.PrimaryKeyField,bean.getKeyValue()+""), doc);
        	}
        	//indexWriter.optimize();
            
            indexWriter.forceMerge(1);
            indexWriter.commit();    
            indexWriter.close(); 
	  	}catch(Exception ex){
	  		ex.printStackTrace();
	  	}
	}
	
	public void updateIndex(AbstractBean bean){
		Directory directory = null;     
	    IndexWriter indexWriter = null;     
		try{
			
			  
			directory = FSDirectory.open(this.getIndexFolder(bean.getClass()));     
			indexWriter = new IndexWriter(directory, analyzer, false, IndexWriter.MaxFieldLength.UNLIMITED);     
            indexWriter.setMaxBufferedDocs(maxBufferedDocs);  
            Object[] arr = null;
            if(this.fields!=null && !"".equals(fields)){
            	arr = fields.split(",");
            }
            else{
            	arr =bean.keySet().toArray();
            }
           
           
            Document doc = new Document();   
        	
            for(int i=0;i<arr.length;i++){
           
            	String f = arr[i]+"";
            	 Field key =null;
            	if(f.equals(bean.PrimaryKeyField)){
            		key = new Field(f, bean.getStringValue(f), Field.Store.YES,Field.Index.NOT_ANALYZED, TermVector.NO);
            	}
            	else{
            		 key = new Field(f, bean.getStringValue(f), Field.Store.YES,Field.Index.NOT_ANALYZED, TermVector.NO);  
            	}
                doc.add(key); 
                   
            }
           
            
            indexWriter.updateDocument(new Term(bean.PrimaryKeyField,bean.getKeyValue()+""), doc);
            //indexWriter.optimize();
            //indexWriter.commit(); 
            indexWriter.close();
           

        	
	  	}catch(Exception ex){
	  		ex.printStackTrace();
	  	}
	}
	
	
	
	public   List<DataRow> search(String fields,String key){	
		String [] arr = fields.split(","); 
		return this.search(arr, key);
	}
	
	
	public   List<DataRow> search(SqlFilter filter){	
		List<DataRow>  rows = new ArrayList<DataRow>();
		try{
			System.out.println(filter.getFilterExpress());
			BooleanQuery bQuery = this.createWildcardQuery(filter);
			Directory dir = FSDirectory.open(this.getIndexFolder(this.modelClass));
			IndexReader reader = IndexReader.open(dir);
			this.searcher = new IndexSearcher(reader);
			TopDocs topDocs = this.searcher.search(bQuery, 1000);
	        ScoreDoc[] scoreDocs = topDocs.scoreDocs;
	        String[] arr = this.fields.split(",");
	        for(int i=0;i<scoreDocs.length;i++){
	        	int id = scoreDocs[i].doc; 
	        	Document doc = searcher.doc(id);
	        	DataRow row = new DataRow();
	        	for(int j=0;j<arr.length;j++){
	        		String field = arr[j];
	        		row.set(field, doc.get(field));
	        	}
	        	rows.add(row);
	        	
	        }
		}catch(Exception ex){
			ex.printStackTrace();
		}
        return rows;
	}
	
	public  String searchValues(SqlFilter filter,String field){	

		String strValues="";
		try{
			System.out.println(filter.getFilterExpress());
			ArrayList<String> list = new ArrayList<String>();
			BooleanQuery bQuery = this.createWildcardQuery(filter);
 			Directory dir = FSDirectory.open(this.getIndexFolder(this.modelClass));
			IndexReader reader = IndexReader.open(dir);
			this.searcher = new IndexSearcher(reader);
 			SortField[] sortFields = null; 
 			if(this.order!=null && !"".equals(this.order)){
 				Pattern pattern =Pattern.compile("order\\s+by.*(?i)(asc|desc)?");
 				Matcher m0 = pattern.matcher(this.order);
 				if(m0.find()){
 					String strOrder = m0.group();
 					String str = strOrder.replaceAll("order\\s+by", "").replaceAll("(?i)(asc|desc)", "");
 	 				String[] fields = str.split(",");
 	 				sortFields = new SortField[fields.length];
 	 				//sortFields[0]=SortField.FIELD_SCORE;
 	 				 
 	 				boolean reverse = false; 	 				
 	 				if(this.order.indexOf("desc")!=-1 || this.order.indexOf("DESC")!=-1 || this.order.indexOf("Desc")!=-1){
 	 					reverse  = true;
 	 				}
 	 				for(int i=0;i<fields.length;i++){
 	 					String f = fields[i];
 	 					String [] arr = f.split("\\.");
 	 					if(arr.length>1){
 	 						f= arr[1];
 	 					}
 	 					sortFields[i] =new SortField(f, SortField.DOC,reverse);
 	 				}
 	 				
 	 				//Sort sort = new Sort(sortFields[0],true);
 	 				Sort sort = new Sort(sortFields);
 	 				//sort.INDEXORDER
 	 				TopFieldCollector c = TopFieldCollector.create(sort, this.startIndex+this.searchLimit, false, false, false, false);
 	 				searcher.search(bQuery, c);
 		            ScoreDoc[] hits = c.topDocs(startIndex, searchLimit).scoreDocs;
 		            for (int i = 0; i < hits.length; i++){
 		                 Document doc = searcher.doc(hits[i].doc);
 		                 String key = doc.get(field);
 		 	        	if(key!=null && !"".equals(key) && !list.contains(key)){
 		 	        		String spit = strValues.equals("")?"":",";
 		 	        		strValues+=spit+"'"+key+"'";
 		 	        		list.add(key);
 		 	        	}
 		             }
 				}
 				
	            
 			}
 			
 			
 			/*if(maxDoc.equals("")){
 				topDocs = this.searcher.search(bQuery,searcher.maxDoc());	
 			}
 			else{
 				topDocs = this.searcher.search(bQuery,Integer.parseInt(maxDoc));
 			}*/
 			
 			
	       /* ScoreDoc[] scoreDocs = topDocs.scoreDocs;
	        for(int i=0;i<scoreDocs.length;i++){
	        	int id = scoreDocs[i].doc; 
	        	Document doc = searcher.doc(id);
	        	String key = doc.get(field);
	        	if(key!=null && !"".equals(key) && !list.contains(key)){
	        		String spit = strValues.equals("")?"":",";
	        		strValues+=spit+"'"+key+"'";
	        		list.add(key);
	        	}
	        }*/
	        System.out.println("match num:"+list.size());
		}catch(Exception ex){
			ex.printStackTrace();
		}
        return strValues;
	}
	
	public  int getMatchCount(SqlFilter filter){	
		ArrayList<String> list = new ArrayList<String>();
		try{
			BooleanQuery bQuery = this.createWildcardQuery(filter);
			Directory dir = FSDirectory.open(this.getIndexFolder(this.modelClass));
			IndexReader reader = IndexReader.open(dir);
			this.searcher = new IndexSearcher(reader);
			
			if(this.order!=null && !"".equals(this.order)){
				 
 				String str = this.order.replaceFirst("order\\s+by", "").replaceAll("(asc|desc)", "");
 				String[] fields = str.split(",");
 				SortField[] sortFields = new SortField[fields.length];
 				for(int i=0;i<fields.length;i++){
 					sortFields[i] =new SortField(fields[i], SortField.STRING,false);
 				}
 				Sort sort = new Sort(sortFields);
 				TopFieldCollector c = TopFieldCollector.create(sort, this.startIndex+this.searchLimit, false, false, false, false);
				searcher.search(bQuery, c);
				int num = c.topDocs(startIndex, searchLimit).totalHits;
				System.out.println("match num:"+num);
				return  num;
			}
			
			TopDocs topDocs = this.searcher.search(bQuery,searcher.maxDoc());
	        ScoreDoc[] scoreDocs = topDocs.scoreDocs;
	        for(int i=0;i<scoreDocs.length;i++){
	        	int id = scoreDocs[i].doc; 
	        	Document doc = searcher.doc(id);
	        	String key = doc.get(this.bean.PrimaryKeyField);
	        	if(key!=null && !"".equals(key) && !list.contains(key)){
	        		list.add(key);
	        	}
	        }
	        System.out.println("match num:"+list.size());
		}catch(Exception ex){
			ex.printStackTrace();
		}
        return list.size();
	}
	
	public  SqlFilter getFilter (SqlFilter filter){	
		
		SqlFilter filterClone = filter.clone();
		
		filterClone.attachCondition="";
		
		if(filterClone.getFilterExpress().equals("") || !filter.attachCondition.trim().equals("")){
			return filter;
		}
		if(this.bean==null){
			this.bean = (LuceneIndex)BeanFactory.LoadBean(modelClass);
		}
		if(filter.containsField(bean.PrimaryKey))
			return filter;
		
		if(bean.Parent!=null && filter.containsField(bean.Parent.foreignColumn))
			return filter; 
		
		String strValues = searchValues(filter,bean.PrimaryKeyField);
		String maxDoc = ConfigReader.GetProptery("index.max.hits");
		
		if(!maxDoc.equals("")){
			if(strValues.split(",").length>Integer.parseInt(maxDoc)){
				return filter;
			}
		}
		
		int fieldSize = filter.size()+filter.childMap.size();
		filter.removeAll();
		if(strValues.equals("") && fieldSize>0){
			filter.addFilter(bean.PrimaryKey, SqlFilter.OP.EQUALS,-1);
		}
		else if(!strValues.equals("")){
			filter.attachCondition = filter.attachCondition + " and "+bean.PrimaryKey +" in ("+strValues+")";
		}
		this.usingLuceneQuery = true;
		
		return filter;
	}
	
	public  SqlFilter getFilter (SqlFilter filter,String order,int limit){	
		this.order = order;
		this.searchLimit = limit;
		return this.getFilter(filter);
	}
	
	
	
	public BooleanQuery createWildcardQuery(String[] fields,String key,BooleanClause.Occur occur){
		BooleanQuery bQuery = new BooleanQuery(); 
		for(int i=0;i<fields.length;i++){
	       	 Query queryOBJ = new WildcardQuery(new Term(fields[i], "*"+key+"*")); 
	       	 bQuery.add(queryOBJ,occur);
        }
		return bQuery;
	}
	
	public BooleanQuery createWildcardQuery(String fields,String key,BooleanClause.Occur occur){
		String [] arr = fields.split(",");
		return this.createWildcardQuery(arr,key,occur);
	}
	
	public BooleanQuery createTermQuery(String[] fields,String key,BooleanClause.Occur occur){
		BooleanQuery bQuery = new BooleanQuery(); 
		for(int i=0;i<fields.length;i++){
			Query  queryOBJ = new TermQuery(new Term(fields[i], key)); 
	       	bQuery.add(queryOBJ,occur);
        }
		return bQuery;
	}
	
	public BooleanQuery createTermQuery( String fields,String key,BooleanClause.Occur occur){
		String [] arr = fields.split(",");
		return this.createTermQuery(arr,key,occur);
	}
	
	public BooleanQuery createTermQuery( SqlFilter filter){
		BooleanQuery bQuery = new BooleanQuery(); 
		Object[] fields = filter.filterMap.keySet().toArray();
		for(int i=0;i<fields.length;i++){
			String key = fields[i]+"";
			String value = filter.getValue(key)+"";
			value = value.replace("%", "");
			Query  queryOBJ = new TermQuery(new Term(key, value)); 
	       	bQuery.add(queryOBJ,BooleanClause.Occur.MUST);
		}
		if(filter.getChildSize()>0){
			addChildTermQuery(bQuery,filter.childMap);
		}
		return bQuery;
	}
	
	public void addChildTermQuery( BooleanQuery bQuery,HashMap<SqlFilter,String> childMap){
		Object[] fields =childMap.keySet().toArray();
		for(int i=0;i<fields.length;i++){
			SqlFilter childFilter = (SqlFilter)fields[i];
			String op = (String) childMap.get(childFilter);
			BooleanQuery childQuery = createTermQuery(childFilter);
			BooleanClause.Occur occur = op.trim().equals("and")?BooleanClause.Occur.MUST:BooleanClause.Occur.SHOULD;
			bQuery.add(childQuery, occur);
		}
	}
	
	
	
	public BooleanQuery createWildcardQuery( SqlFilter filter) {
		
		BooleanQuery bQuery = new BooleanQuery(); 
		
		
		try{
			Object[] fields = filter.filterMap.keySet().toArray();
			for(int i=0;i<fields.length;i++){
				String key = fields[i]+"";
				String op = filter.getOperation(key);
				Pattern p = Pattern.compile("(\\^\\d+)");
	            Matcher m = p.matcher(key);

	            if (m.find()) {
	            	key = m.replaceAll("");
	            }
	            String value = filter.getValue(key)+"";
				value = value.replace("%", "").toLowerCase();
				Term term =new Term(key,value);
				Query queryOBJ = null;
				if(this.bean.containsSpecialField(key)){
					queryOBJ = bean.getSpecialQuery(key, term);
				}
				else{
					queryOBJ =new WildcardQuery(new Term(key, "*"+value+"*")); 
				}
				if(op.trim().equals("=") || op.trim().indexOf("like")!=-1){
					bQuery.add(queryOBJ,BooleanClause.Occur.MUST);
				}
				else if(op.trim().equals("<>")){
					bQuery.add(queryOBJ,BooleanClause.Occur.MUST_NOT);
				}
			    
			}
			String attachCondition = filter.attachCondition;
			
			
			if(filter.getChildSize()>0){
				bQuery = addChildWildcardQuery(bQuery,filter);
			}
		}catch(Exception ex){
			ex.printStackTrace();
		}
		return bQuery;
	}
	
	List<Query>getQueryByCondition( String condition){
		condition = condition.toLowerCase();
		List<Query> querys = new ArrayList<Query>();
		if(!"".equals(condition)){
			String[] arr = condition.split("and");
			for(int i=0;i<arr.length;i++){
				String exp = arr[i].trim();
				Query queryOBJ  = null;
				if(Pattern.compile("is\\s+null").matcher(exp).find()){
					String field = exp.split("\\s+")[0];
					queryOBJ  = new TermQuery(new Term(field ,"\\(null\\)"));
					//Query queryOBJ =new WildcardQuery(new Term(key, "*"+value+"*"));
				}else  if(Pattern.compile("not\\s+in\\s+(*?)").matcher(exp).find()){
					String field = exp.split("\\s+")[0];
					//String value = 
					queryOBJ  = new TermQuery(new Term(field ,"\\(null\\)"));
					//Query queryOBJ =new WildcardQuery(new Term(key, "*"+value+"*"));
				}
				querys.add(queryOBJ);
				
			}
			
		}
		return querys ;
	}
	
	public BooleanQuery addChildWildcardQuery(BooleanQuery bQuery,SqlFilter filter) {
		
		BooleanQuery query = new BooleanQuery();
		if(bQuery.clauses().size()>0){
			query.add(bQuery, BooleanClause.Occur.SHOULD);
		}
		Object[] fields = filter.childMap.keySet().toArray();
		for (int i = 0; i < fields.length; i++) {
			SqlFilter childFilter = (SqlFilter) fields[i];
			String op = (String) filter.childMap.get(childFilter);
			String strExpress = childFilter.getFilterExpress();
			if(strExpress.equals("")){
				continue;
			}
			BooleanQuery childQuery = createWildcardQuery(childFilter);
			
			if (childQuery.clauses().size() > 0) {
				BooleanClause.Occur occur = op.toLowerCase().trim().equals("and") ? 
						BooleanClause.Occur.MUST: BooleanClause.Occur.SHOULD;
				query.add(childQuery, occur);
			}

		}
		return query;
	}
	
	
	
	
	
	public  List<DataRow> search(String[] fields,String key){
		
		List<DataRow>  rows = new ArrayList<DataRow>();
		try{
			BooleanQuery bQuery = new BooleanQuery(); 
			Directory dir = FSDirectory.open(this.getIndexFolder(this.bean.getClass()));   
			if(dir.listAll().length==0){
				return rows;
			}
			IndexReader reader = IndexReader.open(dir);
			this.searcher = new IndexSearcher(reader);
		
	        for(int i=0;i<fields.length;i++){
		       	 Query queryOBJ = new WildcardQuery(new Term(fields[i], "*"+key+"*")); 
		       	 bQuery.add(queryOBJ, BooleanClause.Occur.SHOULD);
	        }

	        TopDocs topDocs = this.searcher.search(bQuery, 1000);
	        ScoreDoc[] scoreDocs = topDocs.scoreDocs;
	        for(int i=0;i<scoreDocs.length;i++){
	        	int id = scoreDocs[i].doc; 
	        	Document doc = searcher.doc(id);
	        	DataRow row = new DataRow();
	        	for(int j=0;j<fields.length;j++){
	        		String field = fields[j];
	        		row.set(field, doc.get(field));
	        	}
	        	rows.add(row);
	        	
	        }
	        
		}catch(Exception ex){
			ex.printStackTrace();
		}
		return rows;
	}
	
	public void saveIndex(ArrayList<AbstractBean> list){
		Directory directory = null;     
	    IndexWriter indexWriter = null;     
		try{
			
			if(list==null ||  list.size()==0){
				return;
			}
			LuceneIndex first = (LuceneIndex)list.get(0);
			String[] special_fields = first.special_fields;
			Field.Index[] indexs = first.special_index;
		
			
			directory = FSDirectory.open(this.getIndexFolder(first.getClass()));    
			//directory = FSDirectory.getDirectory(rootFolder);     
            indexWriter = new IndexWriter(directory, analyzer, true, IndexWriter.MaxFieldLength.UNLIMITED);     
            indexWriter.setMaxBufferedDocs(maxBufferedDocs);  
            Object[] arr = null;
            
            for(int j=0;j<list.size();j++){
            	 Document doc = new Document();   
            	 AbstractBean item = list.get(j);
            	 if(item.PrimaryKeyField==null || item.PrimaryKeyField.equals("")){
            		 item.PrimaryKeyField = item.PrimaryKey;
                 }
            	 if(this.fields!=null && !"".equals(this.fields)){
                 	arr = fields.split(",");
                 }
                 else{
                 	arr = item.keySet().toArray();
                 }
                 for(int i=0;i<arr.length;i++){
                 	
                 	String f = arr[i]+"";
                 	Field key =null;
                 	
                 	if(this.bean.containsSpecialField(f)){
                 		key = new Field(f, item.getStringValue(f).toLowerCase(), Field.Store.YES,bean.getSpecialIndex(f), TermVector.YES);
                 	}
                 	else{
                 		//Field.Index.TOKENIZED
                 		String value = item.getStringValue(f);
                 		if("".equals(value)){
                 			value="(null)";
                 		}
                 		key = new Field(f, value.toLowerCase(), Field.Store.YES,Field.Index.NOT_ANALYZED, TermVector.YES);
                 	}
                    doc.add(key); 
                   
                 }
                 
                 indexWriter.addDocument(doc);     
            }
            //indexWriter.optimize();   
            indexWriter.forceMerge(1);
            indexWriter.commit();    
            indexWriter.close(); 
	  	}catch(Exception ex){
	  		ex.printStackTrace();
	  	}
	}
	
	public void updateIndex(ArrayList<AbstractBean> list){
		Directory directory = null;     
	    IndexWriter indexWriter = null;     
		try{
			
			if(list==null ||  list.size()==0){
				return;
			}
			LuceneIndex first = (LuceneIndex)list.get(0);
			String[] special_fields = first.special_fields;
			Field.Index[] indexs = first.special_index;
			//String[] queryTypes = first.queryType;
			
			directory = FSDirectory.open(this.getIndexFolder(first.getClass()));    
			//directory = FSDirectory.getDirectory(rootFolder);     
            indexWriter = new IndexWriter(directory, analyzer, false, IndexWriter.MaxFieldLength.UNLIMITED);     
            indexWriter.setMaxBufferedDocs(maxBufferedDocs);  
            Object[] arr = null;
            
            for(int j=0;j<list.size();j++){
            	 Document doc = new Document();   
            	 AbstractBean item = list.get(j);
            	 if(item.PrimaryKeyField==null || item.PrimaryKeyField.equals("")){
            		 item.PrimaryKeyField = item.PrimaryKey;
                 }
            	 if(this.fields!=null && !"".equals(this.fields)){
                 	arr = fields.split(",");
                 }
                 else{
                 	arr = item.keySet().toArray();
                 }
                 for(int i=0;i<arr.length;i++){
                 	
                 	String f = arr[i]+"";
                 	Field key =null;
                 	
                 	if(this.bean.containsSpecialField(f)){
                 		key = new Field(f, item.getStringValue(f).toLowerCase(), Field.Store.YES,bean.getSpecialIndex(f), TermVector.NO);
                 	}
                 	else{
                 		//Field.Index.TOKENIZED
                 		 key = new Field(f, item.getStringValue(f).toLowerCase(), Field.Store.YES,Field.Index.NOT_ANALYZED, TermVector.YES);
                 	}
                    doc.add(key); 
                   
                 }
                 
                 indexWriter.updateDocument(new Term(item.PrimaryKeyField,item.getKeyValue()+""), doc);
            }
            //indexWriter.optimize();   
            indexWriter.commit();    
            indexWriter.close(); 
	  	}catch(Exception ex){
	  		ex.printStackTrace();
	  	}
	}
	
	
	
	private File getIndexFolder(Class beanClass){
		String name = this.floderName;
		if(name == null || "".equals(name)){
			name = beanClass.getSimpleName();
		}
		File indexFloder = null;
		if(this.floderPath == null || "".equals(this.floderPath)){
			this.floderPath = ConfigReader.GetProptery(LuceneUtils.INDEX_FLODER_KEY);
		}
		if(this.floderPath == null || "".equals(this.floderPath)){
			return null;
		}
		
		rootFolder = new File(this.floderPath);     
		if(!rootFolder.exists()) {     
            rootFolder.mkdir();     
        }
		indexFloder = new File( rootFolder + File.separator + name );
		if(!indexFloder.exists()) {     
			indexFloder.mkdir();     
        }
		return indexFloder;
	}
	
	private String getIndexFolderPath(Class beanClass){
		String filePath = "";
		String name = beanClass.getSimpleName();
		File indexFloder = null;
		if(this.floderPath == null || "".equals(this.floderPath)){
			this.floderPath = ConfigReader.GetProptery(INDEX_FLODER_KEY);
		}
		if(this.floderPath == null || "".equals(this.floderPath)){
			return "";
		}
		
		rootFolder = new File(this.floderPath);     
		if(!rootFolder.exists()) {     
            rootFolder.mkdir();     
        }
		filePath = rootFolder+ File.separator+name;
		indexFloder = new File(filePath);
		if(!indexFloder.exists()) {     
			indexFloder.mkdir();     
        }
		return filePath;
	}
	
	
	
	
}
